From 8e553531464013c561dd276ef014309a1e732760 Mon Sep 17 00:00:00 2001 From: "cl349@freefall.cl.cam.ac.uk" Date: Tue, 10 Aug 2004 17:22:40 +0000 Subject: [PATCH] bitkeeper revision 1.1159.11.2 (41190460g_46PGXC611SAS9fnIgORA) Fix CONFIG_HIGHMEM. --- .rootkeys | 2 + linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig | 16 +- .../arch/xen/i386/mm/Makefile | 2 +- .../arch/xen/i386/mm/highmem.c | 137 ++++++++++++++++++ .../arch/xen/i386/mm/pgtable.c | 10 +- .../include/asm-xen/asm-i386/highmem.h | 72 +++++++++ .../include/asm-xen/asm-i386/pgtable.h | 6 +- 7 files changed, 233 insertions(+), 12 deletions(-) create mode 100644 linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c create mode 100644 linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h diff --git a/.rootkeys b/.rootkeys index bdeeb555d1..0de7d92f81 100644 --- a/.rootkeys +++ b/.rootkeys @@ -153,6 +153,7 @@ 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.7-xen-sparse/arch/xen/i386/kernel/vsyscall.lds 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.7-xen-sparse/arch/xen/i386/mm/fault.c +4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.7-xen-sparse/arch/xen/i386/mm/hypervisor.c 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.7-xen-sparse/arch/xen/i386/mm/init.c 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -200,6 +201,7 @@ 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h 40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/e820.h 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/fixmap.h +4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/io.h 40f5623am9BzluYFuV6EQfTd-so3dA linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/mach-xen/do_timer.h 40f5623adZQ1IZGPxbDXONjyZGYuTA linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/mach-xen/io_ports.h diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig b/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig index 0cfb2d40a6..1a051d436d 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig @@ -555,14 +555,14 @@ config HAVE_ARCH_BOOTMEM_NODE depends on NUMA default y -config HIGHPTE - bool "Allocate 3rd-level pagetables from highmem" - depends on HIGHMEM4G || HIGHMEM64G - help - The VM uses one page table entry for each page of physical memory. - For systems with a lot of RAM, this can be wasteful of precious - low memory. Setting this option will put user-space page table - entries in high memory. +#config HIGHPTE +# bool "Allocate 3rd-level pagetables from highmem" +# depends on HIGHMEM4G || HIGHMEM64G +# help +# The VM uses one page table entry for each page of physical memory. +# For systems with a lot of RAM, this can be wasteful of precious +# low memory. Setting this option will put user-space page table +# entries in high memory. #config MTRR # bool "MTRR (Memory Type Range Register) support" diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile index a0f3470825..55063591f0 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile @@ -11,7 +11,7 @@ c-obj-y := extable.o pageattr.o c-obj-$(CONFIG_DISCONTIGMEM) += discontig.o c-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o -c-obj-$(CONFIG_HIGHMEM) += highmem.o +obj-$(CONFIG_HIGHMEM) += highmem.o c-obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o c-link := diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c new file mode 100644 index 0000000000..6b6fd16514 --- /dev/null +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c @@ -0,0 +1,137 @@ +#include + +void *kmap(struct page *page) +{ + might_sleep(); + if (page < highmem_start_page) + return page_address(page); + return kmap_high(page); +} + +void kunmap(struct page *page) +{ + if (in_interrupt()) + BUG(); + if (page < highmem_start_page) + return; + kunmap_high(page); +} + +/* + * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because + * no global lock is needed and because the kmap code must perform a global TLB + * invalidation when the kmap pool wraps. + * + * However when holding an atomic kmap is is not legal to sleep, so atomic + * kmaps are appropriate for short, tight code paths only. + */ +void *kmap_atomic(struct page *page, enum km_type type) +{ + enum fixed_addresses idx; + unsigned long vaddr; + + /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + inc_preempt_count(); + if (page < highmem_start_page) + return page_address(page); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + if (!pte_none(*(kmap_pte-idx))) + BUG(); +#endif + set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); + __flush_tlb_one(vaddr); + + return (void*) vaddr; +} + +/* Same as kmap_atomic but with PAGE_KERNEL_RO page protection */ +void *kmap_atomic_pte(struct page *page, enum km_type type) +{ + enum fixed_addresses idx; + unsigned long vaddr; + + /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + inc_preempt_count(); + if (page < highmem_start_page) + return page_address(page); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + if (!pte_none(*(kmap_pte-idx))) + BUG(); +#endif + set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL_RO)); + __flush_tlb_one(vaddr); + + return (void*) vaddr; +} + +void kunmap_atomic(void *kvaddr, enum km_type type) +{ +#ifdef CONFIG_DEBUG_HIGHMEM + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + if (vaddr < FIXADDR_START) { // FIXME + dec_preempt_count(); + preempt_check_resched(); + return; + } + + if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) + BUG(); + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(kmap_pte-idx); + __flush_tlb_one(vaddr); +#endif + + dec_preempt_count(); + preempt_check_resched(); +} + +void kunmap_atomic_force(void *kvaddr, enum km_type type) +{ + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + if (vaddr < FIXADDR_START) { // FIXME + dec_preempt_count(); + preempt_check_resched(); + return; + } + + if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) + BUG(); + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(kmap_pte-idx); + __flush_tlb_one(vaddr); + + dec_preempt_count(); + preempt_check_resched(); +} + +struct page *kmap_atomic_to_page(void *ptr) +{ + unsigned long idx, vaddr = (unsigned long)ptr; + pte_t *pte; + + if (vaddr < FIXADDR_START) + return virt_to_page(ptr); + + idx = virt_to_fix(vaddr); + pte = kmap_pte - (idx - FIX_KMAP_BEGIN); + return pte_page(*pte); +} + diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c index cbab491f2e..e9e70e61b0 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c @@ -194,9 +194,17 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); #endif if (pte) { +#ifdef CONFIG_HIGHPTE + void *kaddr = kmap_atomic(pte, KM_USER0); + clear_page(kaddr); + kunmap_atomic_force(kaddr, KM_USER0); +#else clear_highpage(pte); +#endif +#ifdef CONFIG_HIGHPTE + if (pte < highmem_start_page) +#endif __make_page_readonly(phys_to_virt(page_to_pseudophys(pte))); - /* XXXcl highmem */ } return pte; } diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h new file mode 100644 index 0000000000..f608a13755 --- /dev/null +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h @@ -0,0 +1,72 @@ +/* + * highmem.h: virtual kernel memory mappings for high memory + * + * Used in CONFIG_HIGHMEM systems for memory pages which + * are not addressable by direct kernel virtual addresses. + * + * Copyright (C) 1999 Gerhard Wichert, Siemens AG + * Gerhard.Wichert@pdb.siemens.de + * + * + * Redesigned the x86 32-bit VM architecture to deal with + * up to 16 Terabyte physical memory. With current x86 CPUs + * we now support up to 64 Gigabytes physical RAM. + * + * Copyright (C) 1999 Ingo Molnar + */ + +#ifndef _ASM_HIGHMEM_H +#define _ASM_HIGHMEM_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +/* declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +extern pte_t *kmap_pte; +extern pgprot_t kmap_prot; +extern pte_t *pkmap_page_table; + +extern void kmap_init(void); + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +#if NR_CPUS <= 32 +#define PKMAP_BASE (HYPERVISOR_VIRT_START - (1<<23)) +#else +#define PKMAP_BASE (HYPERVISOR_VIRT_START - (1<<23) - 0x200000UL) +#endif +#ifdef CONFIG_X86_PAE +#define LAST_PKMAP 512 +#else +#define LAST_PKMAP 1024 +#endif +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +extern void * FASTCALL(kmap_high(struct page *page)); +extern void FASTCALL(kunmap_high(struct page *page)); + +void *kmap(struct page *page); +void kunmap(struct page *page); +void *kmap_atomic(struct page *page, enum km_type type); +void *kmap_atomic_pte(struct page *page, enum km_type type); +void kunmap_atomic(void *kvaddr, enum km_type type); +void kunmap_atomic_force(void *kvaddr, enum km_type type); +struct page *kmap_atomic_to_page(void *ptr); + +#define flush_cache_kmaps() do { } while (0) + +#endif /* __KERNEL__ */ + +#endif /* _ASM_HIGHMEM_H */ diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h index be31d10f30..8c8dfaa3df 100644 --- a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -333,9 +333,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address)) + ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + \ + pte_index(address)) #define pte_offset_map_nested(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address)) + ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + \ + pte_index(address)) #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) #else -- 2.30.2